This notebook will begin looking at clustering methods on the expression of the genes in a single sample of the dataset of interest, from an unbiased approach.

Set Up

# Load libraries
library(magrittr)
library(scater)
Loading required package: SingleCellExperiment
Loading required package: SummarizedExperiment
Loading required package: MatrixGenerics
Loading required package: matrixStats

Attaching package: ‘MatrixGenerics’

The following objects are masked from ‘package:matrixStats’:

    colAlls, colAnyNAs, colAnys, colAvgsPerRowSet, colCollapse, colCounts, colCummaxs, colCummins, colCumprods, colCumsums, colDiffs, colIQRDiffs,
    colIQRs, colLogSumExps, colMadDiffs, colMads, colMaxs, colMeans2, colMedians, colMins, colOrderStats, colProds, colQuantiles, colRanges,
    colRanks, colSdDiffs, colSds, colSums2, colTabulates, colVarDiffs, colVars, colWeightedMads, colWeightedMeans, colWeightedMedians,
    colWeightedSds, colWeightedVars, rowAlls, rowAnyNAs, rowAnys, rowAvgsPerColSet, rowCollapse, rowCounts, rowCummaxs, rowCummins, rowCumprods,
    rowCumsums, rowDiffs, rowIQRDiffs, rowIQRs, rowLogSumExps, rowMadDiffs, rowMads, rowMaxs, rowMeans2, rowMedians, rowMins, rowOrderStats,
    rowProds, rowQuantiles, rowRanges, rowRanks, rowSdDiffs, rowSds, rowSums2, rowTabulates, rowVarDiffs, rowVars, rowWeightedMads,
    rowWeightedMeans, rowWeightedMedians, rowWeightedSds, rowWeightedVars

Loading required package: GenomicRanges
package ‘GenomicRanges’ was built under R version 4.1.2Loading required package: stats4
Loading required package: BiocGenerics

Attaching package: ‘BiocGenerics’

The following objects are masked from ‘package:stats’:

    IQR, mad, sd, var, xtabs

The following objects are masked from ‘package:base’:

    anyDuplicated, append, as.data.frame, basename, cbind, colnames, dirname, do.call, duplicated, eval, evalq, Filter, Find, get, grep, grepl,
    intersect, is.unsorted, lapply, Map, mapply, match, mget, order, paste, pmax, pmax.int, pmin, pmin.int, Position, rank, rbind, Reduce,
    rownames, sapply, setdiff, sort, table, tapply, union, unique, unsplit, which.max, which.min

Loading required package: S4Vectors

Attaching package: ‘S4Vectors’

The following objects are masked from ‘package:base’:

    expand.grid, I, unname

Loading required package: IRanges
Loading required package: GenomeInfoDb
Loading required package: Biobase
Welcome to Bioconductor

    Vignettes contain introductory material; view with 'browseVignettes()'. To cite Bioconductor, see 'citation("Biobase")', and for packages
    'citation("pkgname")'.


Attaching package: ‘Biobase’

The following object is masked from ‘package:MatrixGenerics’:

    rowMedians

The following objects are masked from ‘package:matrixStats’:

    anyMissing, rowMedians

Loading required package: scuttle
Loading required package: ggplot2
library(readr)
library(bluster)
library(ggpubr)
library(pheatmap)

# Set file paths
data_dir <- file.path("results", "Gawad_processed_data")

# Source custom functions script
source(file.path("utils", "clustering-functions.R"))

Read in data

sample_290_normalized <- read_rds(
  file.path(data_dir, "SCPCS000216", "SCPCL000290_miQC_downstream_processed_normalized_reduced_sce.rds"))

Perform clustering

k-means

kmeans_cluster_names <- colnames(colData(sample_290_normalized)[, "\^kmeans\"])
Error: '\^' is an unrecognized escape in character string starting ""\^"
NA

graph-based, walktrap

# Perform graph-based walktrap clustering
sample_290_normalized <- graph_clustering(
  sample_290_normalized,
  params_range = c(5:25),
  increments = 5,
  weighting_type = "rank",
  cluster_function = "walktrap",
  check_stability = TRUE
)
detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'
# grab column names with clustering results
walktrap_cols <- grep("walktrap", colnames(colData(sample_290_normalized)))
walktrap_cluster_names <- colnames(colData(sample_290_normalized)[, walktrap_cols])

# Plot
walktrap_plot_list <- walktrap_cluster_names %>%
   purrr::map(~ plotReducedDim(sample_290_normalized, dimred = "UMAP", colour_by = .x) + 
                theme_bw() +
                theme(text = element_text(size = 22)))

cowplot::plot_grid(plotlist = walktrap_plot_list, ncol = 3)

graph-based, louvain

# Perform graph-based louvain clustering
sample_290_normalized <- graph_clustering(
  sample_290_normalized,
  params_range = c(5:25),
  increments = 5,
  weighting_type = "jaccard",
  cluster_function = "louvain",
  check_stability = TRUE
)
detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'
# grab column names with clustering results
louvain_cols <- grep("walktrap", colnames(colData(sample_290_normalized)))
louvain_cluster_names <- colnames(colData(sample_290_normalized)[, louvain_cols])

# Plot
louvain_plot_list <- louvain_cluster_names %>%
   purrr::map(~ plotReducedDim(sample_290_normalized, dimred = "UMAP", colour_by = .x) + 
                theme_bw() +
                theme(text = element_text(size = 22)))


cowplot::plot_grid(plotlist = louvain_plot_list, ncol = 3)

Check cluster validity stats

k-means

# Check the k-means cluster validity stats for each of the clusters and return
# stats in a data frame
kmeans_stats_df <- create_metadata_stats_df(sample_290_normalized, c(4:10), 1, "kmeans")

# Preview the results
head(kmeans_stats_df)

# Summarize the stats and return in a data frame
kmeans_summary_stats_df <- summarize_clustering_stats(kmeans_stats_df)

# Preview the summary results
head(kmeans_summary_stats_df)

purity plots

# Plot individual cluster purity stats
kmeans_purity_plots <- plot_cluster_purity(kmeans_stats_df)

kmeans_purity_plots

silhouette width plots

# Plot individual cluster silhouette width stats
kmeans_silhouette_plots <- plot_cluster_silhouette_width(kmeans_stats_df)

kmeans_silhouette_plots

graph-based, walktrap

# Check the walktrap cluster validity stats for each of the clusters and return
# stats in a data frame
walktrap_stats_df <- create_metadata_stats_df(sample_290_normalized, c(5:25), 5, "walktrap")
  
# Preview the all stats results
head(walktrap_stats_df)

# Summarize the stats and return in a data frame
walktrap_summary_stats_df <- summarize_clustering_stats(walktrap_stats_df)

# Preview the summary results
head(walktrap_summary_stats_df)

purity plots

# Plot individual cluster purity stats
walktrap_purity_plots <- plot_cluster_purity(walktrap_stats_df)

walktrap_purity_plots

silhouette width plots

# Plot individual cluster silhouette width stats
walktrap_silhouette_plots <- plot_cluster_silhouette_width(walktrap_stats_df)

walktrap_silhouette_plots

graph-based, louvain

# Check the louvain cluster validity stats for each of the clusters and return
# stats in a data frame
louvain_stats_df <- create_metadata_stats_df(sample_290_normalized, c(5:25), 5, "louvain")

# Preview the results
head(louvain_stats_df)

# Summarize the stats and return in a data frame
louvain_summary_stats_df <- summarize_clustering_stats(louvain_stats_df)

# Preview the summary results
head(louvain_summary_stats_df)

purity plots

# Plot individual cluster purity stats
louvain_purity_plots <- plot_cluster_purity(louvain_stats_df)

louvain_purity_plots

silhouette width plots

# Plot individual cluster silhouette width stats
louvain_silhouette_plots <- plot_cluster_silhouette_width(louvain_stats_df)

louvain_silhouette_plots

Check cluster stability

k-means

# Check and plot cluster stability
kmeans_cluster_names %>%
  purrr::walk(~ plot_cluster_stability(sample_290_normalized, .x))

graph-based, walktrap

walktrap_cluster_names %>%
  purrr::walk(~ plot_cluster_stability(sample_290_normalized, .x))

graph-based, louvain

louvain_cluster_names %>%
  purrr::walk(~ plot_cluster_stability(sample_290_normalized, .x))

Session info

sessionInfo()
LS0tCnRpdGxlOiAiQ2x1c3RlcmluZyIKYXV0aG9yOiAiRGF0YSBMYWIgZm9yIEFMU0YiCmRhdGU6ICIyMDIyIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgZGZfcHJpbnQ6IHBhZ2VkCi0tLQoKVGhpcyBub3RlYm9vayB3aWxsIGJlZ2luIGxvb2tpbmcgYXQgY2x1c3RlcmluZyBtZXRob2RzIG9uIHRoZSBleHByZXNzaW9uIG9mIHRoZSBnZW5lcyBpbiBhIHNpbmdsZSBzYW1wbGUgb2YgdGhlIGRhdGFzZXQgb2YgaW50ZXJlc3QsIGZyb20gYW4gdW5iaWFzZWQgYXBwcm9hY2guCgojIyBTZXQgVXAgCgpgYGB7cn0KIyBMb2FkIGxpYnJhcmllcwpsaWJyYXJ5KG1hZ3JpdHRyKQpsaWJyYXJ5KHNjYXRlcikKbGlicmFyeShyZWFkcikKbGlicmFyeShibHVzdGVyKQpsaWJyYXJ5KGdncHVicikKbGlicmFyeShwaGVhdG1hcCkKCiMgU2V0IGZpbGUgcGF0aHMKZGF0YV9kaXIgPC0gZmlsZS5wYXRoKCJyZXN1bHRzIiwgIkdhd2FkX3Byb2Nlc3NlZF9kYXRhIikKCiMgU291cmNlIGN1c3RvbSBmdW5jdGlvbnMgc2NyaXB0CnNvdXJjZShmaWxlLnBhdGgoInV0aWxzIiwgImNsdXN0ZXJpbmctZnVuY3Rpb25zLlIiKSkKYGBgCgojIyBSZWFkIGluIGRhdGEKCmBgYHtyfQpzYW1wbGVfMjkwX25vcm1hbGl6ZWQgPC0gcmVhZF9yZHMoCiAgZmlsZS5wYXRoKGRhdGFfZGlyLCAiU0NQQ1MwMDAyMTYiLCAiU0NQQ0wwMDAyOTBfbWlRQ19kb3duc3RyZWFtX3Byb2Nlc3NlZF9ub3JtYWxpemVkX3JlZHVjZWRfc2NlLnJkcyIpKQpgYGAKCiMjIFBlcmZvcm0gY2x1c3RlcmluZwoKIyMjIGstbWVhbnMKCmBgYHtyIGZpZy5oZWlnaHQgPSAxMC41fQojIFBlcmZvcm0gay1tZWFucyBjbHVzdGVyaW5nCnNhbXBsZV8yOTBfbm9ybWFsaXplZCA8LSBrbWVhbnNfY2x1c3RlcmluZygKICBzYW1wbGVfMjkwX25vcm1hbGl6ZWQsCiAgcGFyYW1zX3JhbmdlID0gYyg0OjEwKSwKICBpbmNyZW1lbnRzID0gMSwKICBjaGVja19zdGFiaWxpdHkgPSBUUlVFCikKCiMgZ3JhYiBjb2x1bW4gbmFtZXMgd2l0aCBjbHVzdGVyaW5nIHJlc3VsdHMKa21lYW5zX2NvbHMgPC0gZ3JlcCgia21lYW5zIiwgY29sbmFtZXMoY29sRGF0YShzYW1wbGVfMjkwX25vcm1hbGl6ZWQpKSkKa21lYW5zX2NsdXN0ZXJfbmFtZXMgPC0gY29sbmFtZXMoY29sRGF0YShzYW1wbGVfMjkwX25vcm1hbGl6ZWQpWywga21lYW5zX2NvbHNdKQoKIyBQbG90IGstbWVhbnMKa21lYW5zX3Bsb3RfbGlzdCA8LSBrbWVhbnNfY29scyAlPiUKICBwdXJycjo6bWFwKH4gcGxvdFJlZHVjZWREaW0oc2FtcGxlXzI5MF9ub3JtYWxpemVkLCBkaW1yZWQgPSAiVU1BUCIsIGNvbG91cl9ieSA9IC54KSArIAogICAgICAgICAgICAgICB0aGVtZV9idygpKwogICAgICAgICAgICAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMikpKQoKY293cGxvdDo6cGxvdF9ncmlkKHBsb3RsaXN0ID0ga21lYW5zX3Bsb3RfbGlzdCwgbmNvbCA9IDQpCmBgYAoKIyMjIGdyYXBoLWJhc2VkLCB3YWxrdHJhcAoKYGBge3IgZmlnLmhlaWdodCA9IDkuNX0KIyBQZXJmb3JtIGdyYXBoLWJhc2VkIHdhbGt0cmFwIGNsdXN0ZXJpbmcKc2FtcGxlXzI5MF9ub3JtYWxpemVkIDwtIGdyYXBoX2NsdXN0ZXJpbmcoCiAgc2FtcGxlXzI5MF9ub3JtYWxpemVkLAogIHBhcmFtc19yYW5nZSA9IGMoNToyNSksCiAgaW5jcmVtZW50cyA9IDUsCiAgd2VpZ2h0aW5nX3R5cGUgPSAicmFuayIsCiAgY2x1c3Rlcl9mdW5jdGlvbiA9ICJ3YWxrdHJhcCIsCiAgY2hlY2tfc3RhYmlsaXR5ID0gVFJVRQopCgojIGdyYWIgY29sdW1uIG5hbWVzIHdpdGggY2x1c3RlcmluZyByZXN1bHRzCndhbGt0cmFwX2NvbHMgPC0gZ3JlcCgid2Fsa3RyYXAiLCBjb2xuYW1lcyhjb2xEYXRhKHNhbXBsZV8yOTBfbm9ybWFsaXplZCkpKQp3YWxrdHJhcF9jbHVzdGVyX25hbWVzIDwtIGNvbG5hbWVzKGNvbERhdGEoc2FtcGxlXzI5MF9ub3JtYWxpemVkKVssIHdhbGt0cmFwX2NvbHNdKQoKIyBQbG90CndhbGt0cmFwX3Bsb3RfbGlzdCA8LSB3YWxrdHJhcF9jbHVzdGVyX25hbWVzICU+JQogICBwdXJycjo6bWFwKH4gcGxvdFJlZHVjZWREaW0oc2FtcGxlXzI5MF9ub3JtYWxpemVkLCBkaW1yZWQgPSAiVU1BUCIsIGNvbG91cl9ieSA9IC54KSArIAogICAgICAgICAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgICAgICAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMikpKQoKY293cGxvdDo6cGxvdF9ncmlkKHBsb3RsaXN0ID0gd2Fsa3RyYXBfcGxvdF9saXN0LCBuY29sID0gMykKYGBgCgojIyMgZ3JhcGgtYmFzZWQsIGxvdXZhaW4KCmBgYHtyIGZpZy5oZWlnaHQgPSA4LjV9CiMgUGVyZm9ybSBncmFwaC1iYXNlZCBsb3V2YWluIGNsdXN0ZXJpbmcKc2FtcGxlXzI5MF9ub3JtYWxpemVkIDwtIGdyYXBoX2NsdXN0ZXJpbmcoCiAgc2FtcGxlXzI5MF9ub3JtYWxpemVkLAogIHBhcmFtc19yYW5nZSA9IGMoNToyNSksCiAgaW5jcmVtZW50cyA9IDUsCiAgd2VpZ2h0aW5nX3R5cGUgPSAiamFjY2FyZCIsCiAgY2x1c3Rlcl9mdW5jdGlvbiA9ICJsb3V2YWluIiwKICBjaGVja19zdGFiaWxpdHkgPSBUUlVFCikKCiMgZ3JhYiBjb2x1bW4gbmFtZXMgd2l0aCBjbHVzdGVyaW5nIHJlc3VsdHMKbG91dmFpbl9jb2xzIDwtIGdyZXAoIndhbGt0cmFwIiwgY29sbmFtZXMoY29sRGF0YShzYW1wbGVfMjkwX25vcm1hbGl6ZWQpKSkKbG91dmFpbl9jbHVzdGVyX25hbWVzIDwtIGNvbG5hbWVzKGNvbERhdGEoc2FtcGxlXzI5MF9ub3JtYWxpemVkKVssIGxvdXZhaW5fY29sc10pCgojIFBsb3QKbG91dmFpbl9wbG90X2xpc3QgPC0gbG91dmFpbl9jbHVzdGVyX25hbWVzICU+JQogICBwdXJycjo6bWFwKH4gcGxvdFJlZHVjZWREaW0oc2FtcGxlXzI5MF9ub3JtYWxpemVkLCBkaW1yZWQgPSAiVU1BUCIsIGNvbG91cl9ieSA9IC54KSArIAogICAgICAgICAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgICAgICAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMikpKQoKCmNvd3Bsb3Q6OnBsb3RfZ3JpZChwbG90bGlzdCA9IGxvdXZhaW5fcGxvdF9saXN0LCBuY29sID0gMykKYGBgCgojIyBDaGVjayBjbHVzdGVyIHZhbGlkaXR5IHN0YXRzCgojIyMgay1tZWFucwoKYGBge3IgZmlnLmhlaWdodCA9IDIwLjV9CiMgQ2hlY2sgdGhlIGstbWVhbnMgY2x1c3RlciB2YWxpZGl0eSBzdGF0cyBmb3IgZWFjaCBvZiB0aGUgY2x1c3RlcnMgYW5kIHJldHVybgojIHN0YXRzIGluIGEgZGF0YSBmcmFtZQprbWVhbnNfc3RhdHNfZGYgPC0gY3JlYXRlX21ldGFkYXRhX3N0YXRzX2RmKHNhbXBsZV8yOTBfbm9ybWFsaXplZCwgYyg0OjEwKSwgMSwgImttZWFucyIpCgojIFByZXZpZXcgdGhlIHJlc3VsdHMKaGVhZChrbWVhbnNfc3RhdHNfZGYpCgojIFN1bW1hcml6ZSB0aGUgc3RhdHMgYW5kIHJldHVybiBpbiBhIGRhdGEgZnJhbWUKa21lYW5zX3N1bW1hcnlfc3RhdHNfZGYgPC0gc3VtbWFyaXplX2NsdXN0ZXJpbmdfc3RhdHMoa21lYW5zX3N0YXRzX2RmKQoKIyBQcmV2aWV3IHRoZSBzdW1tYXJ5IHJlc3VsdHMKaGVhZChrbWVhbnNfc3VtbWFyeV9zdGF0c19kZikKYGBgCgojIyMjIHB1cml0eSBwbG90cwoKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE1fQojIFBsb3QgaW5kaXZpZHVhbCBjbHVzdGVyIHB1cml0eSBzdGF0cwprbWVhbnNfcHVyaXR5X3Bsb3RzIDwtIHBsb3RfY2x1c3Rlcl9wdXJpdHkoa21lYW5zX3N0YXRzX2RmKQoKa21lYW5zX3B1cml0eV9wbG90cwpgYGAKCiMjIyMgc2lsaG91ZXR0ZSB3aWR0aCBwbG90cwoKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE1fQojIFBsb3QgaW5kaXZpZHVhbCBjbHVzdGVyIHNpbGhvdWV0dGUgd2lkdGggc3RhdHMKa21lYW5zX3NpbGhvdWV0dGVfcGxvdHMgPC0gcGxvdF9jbHVzdGVyX3NpbGhvdWV0dGVfd2lkdGgoa21lYW5zX3N0YXRzX2RmKQoKa21lYW5zX3NpbGhvdWV0dGVfcGxvdHMKYGBgCgojIyMgZ3JhcGgtYmFzZWQsIHdhbGt0cmFwCgpgYGB7ciBmaWcuaGVpZ2h0ID0gMTUuNX0KIyBDaGVjayB0aGUgd2Fsa3RyYXAgY2x1c3RlciB2YWxpZGl0eSBzdGF0cyBmb3IgZWFjaCBvZiB0aGUgY2x1c3RlcnMgYW5kIHJldHVybgojIHN0YXRzIGluIGEgZGF0YSBmcmFtZQp3YWxrdHJhcF9zdGF0c19kZiA8LSBjcmVhdGVfbWV0YWRhdGFfc3RhdHNfZGYoc2FtcGxlXzI5MF9ub3JtYWxpemVkLCBjKDU6MjUpLCA1LCAid2Fsa3RyYXAiKQogIAojIFByZXZpZXcgdGhlIGFsbCBzdGF0cyByZXN1bHRzCmhlYWQod2Fsa3RyYXBfc3RhdHNfZGYpCgojIFN1bW1hcml6ZSB0aGUgc3RhdHMgYW5kIHJldHVybiBpbiBhIGRhdGEgZnJhbWUKd2Fsa3RyYXBfc3VtbWFyeV9zdGF0c19kZiA8LSBzdW1tYXJpemVfY2x1c3RlcmluZ19zdGF0cyh3YWxrdHJhcF9zdGF0c19kZikKCiMgUHJldmlldyB0aGUgc3VtbWFyeSByZXN1bHRzCmhlYWQod2Fsa3RyYXBfc3VtbWFyeV9zdGF0c19kZikKYGBgCgojIyMjIHB1cml0eSBwbG90cwoKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE1fQojIFBsb3QgaW5kaXZpZHVhbCBjbHVzdGVyIHB1cml0eSBzdGF0cwp3YWxrdHJhcF9wdXJpdHlfcGxvdHMgPC0gcGxvdF9jbHVzdGVyX3B1cml0eSh3YWxrdHJhcF9zdGF0c19kZikKCndhbGt0cmFwX3B1cml0eV9wbG90cwpgYGAKCiMjIyMgc2lsaG91ZXR0ZSB3aWR0aCBwbG90cwoKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE1fQojIFBsb3QgaW5kaXZpZHVhbCBjbHVzdGVyIHNpbGhvdWV0dGUgd2lkdGggc3RhdHMKd2Fsa3RyYXBfc2lsaG91ZXR0ZV9wbG90cyA8LSBwbG90X2NsdXN0ZXJfc2lsaG91ZXR0ZV93aWR0aCh3YWxrdHJhcF9zdGF0c19kZikKCndhbGt0cmFwX3NpbGhvdWV0dGVfcGxvdHMKYGBgCgojIyMgZ3JhcGgtYmFzZWQsIGxvdXZhaW4KCmBgYHtyIGZpZy5oZWlnaHQgPSA5LjV9CiMgQ2hlY2sgdGhlIGxvdXZhaW4gY2x1c3RlciB2YWxpZGl0eSBzdGF0cyBmb3IgZWFjaCBvZiB0aGUgY2x1c3RlcnMgYW5kIHJldHVybgojIHN0YXRzIGluIGEgZGF0YSBmcmFtZQpsb3V2YWluX3N0YXRzX2RmIDwtIGNyZWF0ZV9tZXRhZGF0YV9zdGF0c19kZihzYW1wbGVfMjkwX25vcm1hbGl6ZWQsIGMoNToyNSksIDUsICJsb3V2YWluIikKCiMgUHJldmlldyB0aGUgcmVzdWx0cwpoZWFkKGxvdXZhaW5fc3RhdHNfZGYpCgojIFN1bW1hcml6ZSB0aGUgc3RhdHMgYW5kIHJldHVybiBpbiBhIGRhdGEgZnJhbWUKbG91dmFpbl9zdW1tYXJ5X3N0YXRzX2RmIDwtIHN1bW1hcml6ZV9jbHVzdGVyaW5nX3N0YXRzKGxvdXZhaW5fc3RhdHNfZGYpCgojIFByZXZpZXcgdGhlIHN1bW1hcnkgcmVzdWx0cwpoZWFkKGxvdXZhaW5fc3VtbWFyeV9zdGF0c19kZikKYGBgCgojIyMjIHB1cml0eSBwbG90cwoKYGBge3IgZmlnLmhlaWdodD0xMH0KIyBQbG90IGluZGl2aWR1YWwgY2x1c3RlciBwdXJpdHkgc3RhdHMKbG91dmFpbl9wdXJpdHlfcGxvdHMgPC0gcGxvdF9jbHVzdGVyX3B1cml0eShsb3V2YWluX3N0YXRzX2RmKQoKbG91dmFpbl9wdXJpdHlfcGxvdHMKYGBgCgojIyMjIHNpbGhvdWV0dGUgd2lkdGggcGxvdHMKCmBgYHtyIGZpZy5oZWlnaHQ9MTB9CiMgUGxvdCBpbmRpdmlkdWFsIGNsdXN0ZXIgc2lsaG91ZXR0ZSB3aWR0aCBzdGF0cwpsb3V2YWluX3NpbGhvdWV0dGVfcGxvdHMgPC0gcGxvdF9jbHVzdGVyX3NpbGhvdWV0dGVfd2lkdGgobG91dmFpbl9zdGF0c19kZikKCmxvdXZhaW5fc2lsaG91ZXR0ZV9wbG90cwpgYGAKCiMjIENoZWNrIGNsdXN0ZXIgc3RhYmlsaXR5CgojIyMgay1tZWFucwoKYGBge3J9CiMgQ2hlY2sgYW5kIHBsb3QgY2x1c3RlciBzdGFiaWxpdHkKa21lYW5zX2NsdXN0ZXJfbmFtZXMgJT4lCiAgcHVycnI6OndhbGsofiBwbG90X2NsdXN0ZXJfc3RhYmlsaXR5KHNhbXBsZV8yOTBfbm9ybWFsaXplZCwgLngpKQpgYGAKCiMjIyBncmFwaC1iYXNlZCwgd2Fsa3RyYXAKCmBgYHtyfQp3YWxrdHJhcF9jbHVzdGVyX25hbWVzICU+JQogIHB1cnJyOjp3YWxrKH4gcGxvdF9jbHVzdGVyX3N0YWJpbGl0eShzYW1wbGVfMjkwX25vcm1hbGl6ZWQsIC54KSkKYGBgCgojIyMgZ3JhcGgtYmFzZWQsIGxvdXZhaW4KCmBgYHtyfQpsb3V2YWluX2NsdXN0ZXJfbmFtZXMgJT4lCiAgcHVycnI6OndhbGsofiBwbG90X2NsdXN0ZXJfc3RhYmlsaXR5KHNhbXBsZV8yOTBfbm9ybWFsaXplZCwgLngpKQpgYGAKCiMjIFNlc3Npb24gaW5mbwoKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBgCg==